#include "udsServer.h"

#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <algorithm>
#include <thread>

#include <sys/un.h>
#include <sys/poll.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>



udsServer::udsServer()
{

}

udsServer::~udsServer()
{
    udsListenThread_.close();
    for ( auto &cfd : pollFdVector_ ) 
    {
        if ( cfd.fd > 0)
            close(cfd.fd);
	}
}


bool udsServer::_checkFds(int chkfd)
{
    auto it = listenFdMap_.find(chkfd);
    if ( it == listenFdMap_.end() )
    {
        return false;
    }
	return true;
}

void udsServer::_removePollFd(int fd)
{
    std::lock_guard<std::mutex> lock(pollFdVectorMutex_);
	auto newend = remove_if(pollFdVector_.begin(), pollFdVector_.end(), [&fd](pollfd &test) {
		return test.fd == fd;
	});
	pollFdVector_.erase(newend, pollFdVector_.end());
}

void udsServer::_pushPollFd(int fd)
{
    std::lock_guard<std::mutex> lock(pollFdVectorMutex_);
    pollfd tmp_poll;
    tmp_poll.fd = fd;
    tmp_poll.events = POLLIN;
    tmp_poll.revents = 0;
    pollFdVector_.emplace_back(tmp_poll);   //emplace_back  和 push 功能一样效率更高  仅 c++11 以后支持  
}

bool udsServer::recvMsg(p_UdsHandler pHandler, int timout)
{
    return  udsCommon::getUdsPacks(pHandler, timout) > 0;    
}

void udsServer::destroyFd(int fd)
{
    if ( fd > 0 )
    {
        _removePollFd(fd);
        close(fd);
    }
}

void udsServer::destroyHandle(p_UdsHandler pHandler)
{
    if ( pHandler->fd > 0 )
    {
        _removePollFd(pHandler->fd);
    }
    udsCommon::destroyHandler(pHandler);
}

void udsServer::udsPollDisponse()
{
    int num = poll(&pollFdVector_[0], pollFdVector_.size(), 2000);
    if (0 >= num) {
        return;
    }
    for ( auto &por : pollFdVector_ ) 
    {
        if ( !por.revents) {
            continue;
        }
        por.revents = 0;

        if ( _checkFds(por.fd) ) 
        {
            int cfd = udsCommon::listenAccpet(por.fd);
            if (cfd > 0) {
                _pushPollFd(cfd);
            }
        } 
        else
        {
            p_UdsHandler pCmd = udsCommon::creatHandler(); 
            pCmd->fd = por.fd;
            // if ( recvMsg(pCmd->fd, (unsigned char *)pCmd->pMsg, pCmd->maxMsgLen, 2000, &pCmd->cmd, pCmd->packsAddr, pCmd->packsSize, &pCmd->packsCount) )
            if ( recvMsg(pCmd, 2000) )
            {
                if ( pCmd->cmd > -1)
                {
                    if(_doCmd(pCmd))
                    {
                        _doCmd_v1(pCmd);
                    }
                    if ( pCmd->isLongLink )
                    {
                        pCmd->fd = -1; // 将 fd 设置为 -1 destroy 时候将不会移除pollFdVector_, 也不关闭fd , 但会释放掉 handler
                    }   
                }
            }
            destroyHandle(pCmd);
        }
    }
}

int udsServer::createListenUds(const char *path)
{
	int lfd = udsCommon::createListenUds(path);
    if ( lfd > 0 )
    {
        listenFdMap_[lfd] = 0;
        _pushPollFd(lfd);
    }

	return lfd;
}

int udsServer::createListenTcp(const int port)
{
	int lfd = udsCommon::createListenTcp(port);
    if ( lfd > 0 )
    {
        listenFdMap_[lfd] = 0;
        _pushPollFd(lfd);
    }

	return lfd;
}

bool udsServer::serverStart()
{
    udsListenThread_.start("[udsServer::udsListenThread_]", this,  &udsServer::udsPollDisponse);
    return true;
}

bool udsServer::insertCb(int cmd, udsFunc func)
{
    auto it = udsFuncMap_.find(cmd);
    if ( it != udsFuncMap_.end() )
    {
        return false;
    }
    udsFuncMap_[cmd] = func;
	return true;
}

bool udsServer::insertCb_v1(int cmd, stdUdsFunc func)
{
    auto it = stdUdsFuncMap_.find(cmd);
    if ( it != stdUdsFuncMap_.end() )
    {
        return false;
    }
    stdUdsFuncMap_[cmd] = func;
	return true;
}

bool udsServer::_doCmd(p_UdsHandler pCmd)
{
    auto it = udsFuncMap_.find(pCmd->cmd);
    if ( it == udsFuncMap_.end() )
    {
        return false;
    }
    udsFuncMap_[pCmd->cmd](pCmd);
    return true;
}

bool udsServer::_doCmd_v1(p_UdsHandler pCmd)
{
    auto it = stdUdsFuncMap_.find(pCmd->cmd);
    if ( it == stdUdsFuncMap_.end() )
    {
        return false;
    }
    stdUdsFuncMap_[pCmd->cmd](pCmd);
    return true;
}

int udsServer::sendMsg(int fd, int cmd, char *p_buf, size_t buf_len)
{
    void *packAddr[MAX_PACKS_NUM] = { 0 };
	size_t packsize[MAX_PACKS_NUM] = { 0 };

    packAddr[0] = p_buf;
    packsize[0] = buf_len;
    return udsCommon::sendPacks(fd, cmd, packAddr, packsize, 1);
}

int udsServer::sendPacks(int fd, int cmd, void **frame_addr, size_t *frame_size, int pack_count)
{
	return udsCommon::sendPacks(fd, cmd, frame_addr, frame_size, pack_count);
}

uds_server_base::uds_server_base(const char * uds_path) {
	if (_init) return;

	_instance = new udsServer();
	if (!_instance) return;

    _instance->createListenUds(uds_path);
	_init = true;
}

uds_server_base::~uds_server_base() {
	if (!_instance) return;
	delete _instance;
	_instance = NULL;
}


void uds_server_base::register_cb(int cmd, void * func(void *)) {
	if (!_instance) return;
	_instance->insertCb(cmd, (udsFunc)func);
}

void uds_server_base::loop() {
	if (!_instance) return;
    _instance->serverStart();
}

